import axios from 'axios';

import { TIME_OUT, API_HOST, PROXY_API, setAccessToken, getAccessToken } from '@utils/config';
import notification from '@utils/notification';
import { BizStatus } from '@enumTypes/enumTypes';

const request = axios.create({
  timeout: TIME_OUT
});

/**
 * 根据状态判断是否有权限
 * @param status
 * @returns { boolean }
 */
const withoutAuthority = (status: number): boolean => {
  if (status === 401) {
    // 跳转到缺失权限界面
    window.history.pushState(null, '', '/un-authorization');
    window.location.reload();

    return false;
  }
  return true;
};

// 请求拦截器: 在发起http请求之前的一些操作
//   1、发送请求之前, 加载一些组件
//   2、某些请求需要携带token, 如果说没有没有携带, 直接跳转到登录页面
request.interceptors.request.use(
  (config: any) => {
    const { url = '', headers = {} } = config;
    // 不带网址则默认为内部通用api(外部接口必须使用完整api, 内部接口可以不使用完整api)
    let actUrl = url;
    if (!/^https?:\/\//.test(url)) {
      // 内部api添加前缀
      actUrl = `${API_HOST}${PROXY_API}${url}`;
    }

    // 非登录接口都需要给接口添加上 token
    if (actUrl !== `${API_HOST}${PROXY_API}/login`) {
      headers.Authorization = getAccessToken();
    }

    // 返回修改后的请求配置
    return {
      ...config,
      url: actUrl,
      headers: { ...headers }
    };
  },
  (err: any) => {
    return Promise.reject(err);
  }
);

// 响应拦截器: 在http请求之后的一些操作
request.interceptors.response.use(
  (res: any) => {
    const { status, data, config } = res;

    // 判断是否401
    if (!withoutAuthority(status)) return;

    // 文件流直接返回数据(不处理)
    if (status === BizStatus.success && config.responseType === 'blob') {
      return res;
    }

    // 无内容返回数据(不处理)
    if (status === 204) {
      return res;
    }

    // 是登录接口并且响应成功时写入token
    if (
      status === 200 &&
      config?.url === `${API_HOST}${PROXY_API}/login` &&
      data?.code === BizStatus.success &&
      data?.success
    ) {
      setAccessToken(data?.data.token);
    }

    if (data && data.failed) {
      notification.error({ message: data?.msg });
      throw data;
    } else {
      // 其余情况-只返回实际的数据
      return data?.data || data;
    }
  },
  (err: any) => {
    // 401处理
    if (!withoutAuthority(err.response?.status)) return;

    // 其余请求报错提示
    if (err && err.response) {
      switch (err.response?.status) {
        case 400:
          notification.error({ message: '请求数据参数或者格式发生错误' });
          break;
        case 404:
          notification.error({ message: '请求接口不存在' });
          break;
        default:
          notification.error({
            message: err.response?.data?.message || '程序出现错误, 请联系管理员'
          });
          break;
      }
    }

    return;
    // // 抛出错误
    // throw err.response;
  }
);

export default request;
